package com.gzz.orchid.context.domain.financial.entity;

import com.gzz.orchid.common.core.tuple.Money;
import com.gzz.orchid.common.core.util.I18nUtil;
import com.gzz.orchid.context.infrastructure.definition.Status;
import lombok.Data;

import java.math.BigDecimal;

/**
 * @author higmd
 */
@Data
public class AccountDo {
    /**
     * 账户编号
     */
    private AccountNo no;
    /**
     * 账户余额
     */
    private Money balance;
    /**
     * 冻结余额
     */
    private Money frozen;
    /**
     * 是否允许透支
     */
    private boolean allowedOverdraft = true;

    /**
     * 透支额度
     */
    private Money overdraftLimit;
    /**
     * 账户状态
     */
    private Status status;

    /**
     * 可用余额
     */
    public Money getAvailableBalance() {
        if (allowedOverdraft) {
            return balance.add(overdraftLimit).subtract(frozen);
        }
        return balance.subtract(frozen);
    }

    /**
     * 透支余额
     */
    public Money getOverdraftBalance() {
        if (allowedOverdraft) {
            if (balance.getValue().compareTo(BigDecimal.ZERO) < 0) {
                return overdraftLimit.add(balance);
            }
            return overdraftLimit;
        } else {
            return Money.ofZero();
        }
    }

    /**
     * 检查可用
     */
    public void checkAvailable(Money amt) {
        if (getAvailableBalance().compare(amt)) {
            throw new IllegalArgumentException(I18nUtil.ofMessage("可用余额不足"));
        }
    }

    /**
     * 检查透支
     */
    public boolean checkOverdraft() {
        if (!allowedOverdraft) {
            return false;
        }
        return balance.getValue().compareTo(BigDecimal.ZERO) < 0;
    }

    /**
     * 冻结 (preDebit)
     */
    public void freeze(Money amt) {
        checkAvailable(amt);
        frozen = frozen.add(amt);
    }

    /**
     * 解冻
     */
    public void unfreeze(Money amt) {
        if (frozen.compare(amt)) {
            throw new IllegalArgumentException(I18nUtil.ofMessage("解冻金额大于冻结金额"));
        }
        frozen = frozen.subtract(amt);
    }

    /**
     * 入账 (withdraw)
     */
    public void credit(Money amt) {
        balance = balance.add(amt);
    }

    /**
     * 出账
     */
    public void debit(Money amt) {
        checkAvailable(amt);
        balance = balance.subtract(amt);
    }
}
